#include <vector>
#include <iostream>
#include <string>
#include <random>
#include <fstream>
#include <iterator>
#include "boost/asio.hpp"
#include <botan/block_cipher.h>
#include <botan/cipher_mode.h>
#include <botan/hex.h>
#include <botan/certstor_system.h>
#include <botan/x509_key.h>
#include <botan/x509cert.h>
#include <botan/x509path.h>
#include <botan/rsa.h>
#include <botan/pubkey.h>
#include <botan/pkcs8.h>
#include <botan/pem.h>
#include <botan/auto_rng.h>
#include <botan/rng.h>

// Modified from origin rfc8446
enum ErrorCode {
    ERR_SUCCESS = 0,
    ERR_DEVICE_NOT_FOUND = 1,
    ERR_NETWORK_FAIL = 2,
    ERR_FILE_ALREADY_EXISTS = 3,
    ERR_PERMISSON_DENY = 4,
    ERROR_VERION_ERROR = 5,
    ERR_INVAILD_DATA = 6,
    ERR_UNKONWN = 100
};

// Modified from origin rfc8446
enum HandshakeType{
    hello_request_RESERVED= 0,
    client_hello= 1,
    server_hello= 2,
    hello_verify_request_RESERVED= 3,
    new_session_ticket= 4,
    end_of_early_data= 5,
    hello_retry_request_RESERVED= 6,
    encrypted_extensions= 8,
    certificate= 11,
    server_key_exchange_RESERVED= 12,
    certificate_request= 13,
    server_hello_done_RESERVED= 14,
    certificate_verify= 15,
    client_key_exchange_RESERVED= 16,
    finished= 20,
    certificate_url_RESERVED= 21,
    certificate_status_RESERVED= 22,
    supplemental_data_RESERVED= 23,
    key_update= 24,
    message_hash= 254,
    shake_empty=255
};

// Modified from origin rfc8446
enum ExtensionType{
    server_name= 0,                             /* RFC 6066 */
    max_fragment_length= 1,                     /* RFC 6066 */
    status_request= 5,                          /* RFC 6066 */
    supported_groups= 10,                       /* RFC 8422, 7919 */
    signature_algorithms= 13,                   /* RFC 8446 */
    use_srtp= 14,                               /* RFC 5764 */
    heartbeat= 15,                              /* RFC 6520 */
    application_layer_protocol_negotiation= 16, /* RFC 7301 */
    signed_certificate_timestamp= 18,           /* RFC 6962 */
    client_certificate_type= 19,                /* RFC 7250 */
    server_certificate_type= 20,                /* RFC 7250 */
    padding= 21,                                /* RFC 7685 */
    pre_shared_key= 41,                         /* RFC 8446 */
    early_data= 42,                             /* RFC 8446 */
    supported_versions= 43,                     /* RFC 8446 */
    cookie= 44,                                 /* RFC 8446 */
    psk_key_exchange_modes= 45,                 /* RFC 8446 */
    certificate_authorities= 47,                /* RFC 8446 */
    oid_filters= 48,                            /* RFC 8446 */
    post_handshake_auth= 49,                    /* RFC 8446 */
    signature_algorithms_cert= 50,              /* RFC 8446 */
    key_share= 51,
    extension_empty=65536
} ;

class Extension{
    public:
        ExtensionType extension_type;
        std::vector<unsigned char> extension_data;
};

class Hello {
    public:
        unsigned short legacy_version = 0x0303;
        unsigned char random [32];
        std::vector<unsigned char> legacy_session_id;
        std::vector<unsigned short> cipher_suites;
        std::vector<unsigned char> legacy_compression_methods;
        std::vector<Extension> extensions;
};

enum CertificateType{
    X509 = 0,
    RawPublicKey = 2,
    certificate_type_empty = 255
} ;

class CertificateEntry {
    public:
        CertificateType certificate_type;
        std::vector<unsigned char> cert_data;
};

class Certificate {
    public:
        std::vector<unsigned char> certificate_request_context;
        std::vector<CertificateEntry> certificate_list;
};

class Handshake {
    public:
        HandshakeType msg_type;
        uint32_t length;
        std::vector<unsigned char> data;
};

struct KeyShareEntry {
    uint16_t group;
    std::vector<unsigned char> key_exchange;
} ;

struct Payload {
    std::vector<unsigned char> payload;
} ;

unsigned short stream_get_short(boost::asio::ip::tcp::iostream& stream);

void parse_extension(Extension& instance, boost::asio::ip::tcp::iostream& stream);
std::vector<unsigned char> wrap_extension(Extension& instance);

void parse_clienthello(Hello& instance, boost::asio::ip::tcp::iostream& stream);
std::vector<unsigned char> wrap_hello(Hello& instance);

void parse_certificate_entry(CertificateEntry& instance, boost::asio::ip::tcp::iostream& stream);
std::vector<unsigned char> wrap_certificate_entry(CertificateEntry& instance);

void parse_certificate(Certificate& instance, boost::asio::ip::tcp::iostream& stream);
std::vector<unsigned char> wrap_certificate(Certificate& instance);

void parse_keyshare(KeyShareEntry& instance, boost::asio::ip::tcp::iostream& stream);
std::vector<unsigned char> wrap_keyshare(KeyShareEntry& instance, bool inverse);

void parse_payload(Payload& instance, boost::asio::ip::tcp::iostream& stream);
std::vector<unsigned char> wrap_payload(Payload& instance, bool inverse);
